package com.xyz.service;

import com.free.common.vo.ResultModel;
import com.free.ext.logger.FreeLogger;
import com.free.ext.logger.FreeLoggerFactory;
import com.free.utils.DateUtils;
import com.free.utils.HttpUtils;
import com.free.utils.RegexUtils;
import com.free.utils.crypt.DESCrypt;
import com.xyz.blockqueue.QueueModel;
import com.xyz.dao.logic.CCustomerOperLogLogic;
import com.xyz.dao.logic.CCustomerfundLogic;
import com.xyz.dao.logic.CCustomerfundflowLogic;
import com.xyz.dao.logic.CustomerLogic;
import com.xyz.domain.constants.ConstantsSysSetting;
import com.xyz.domain.constants.EhCacheConstants;
import com.xyz.domain.constants.SysConstants;
import com.xyz.domain.ext.*;
import com.xyz.domain.model.RegisterModel;
import com.xyz.domain.table.CCustomer;
import com.xyz.domain.table.CCustomerfund;
import com.xyz.domain.table.CCustomerfundflow;
import com.xyz.domain.table.SSetting;
import com.xyz.eventoper.EventOperContext;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;

@Service
public class RegistService extends BaseService {

    private static final FreeLogger LOG = FreeLoggerFactory.getLogger(RegistService.class);

    @Autowired
    private CustomerLogic logic;

    @Autowired
    private CCustomerfundflowLogic customerfundflowLogic;

    @Autowired
    private CCustomerfundLogic customerfundLogic;

    @Autowired
    private CCustomerOperLogLogic customerOperLogLogic;

    @Autowired
    private SSettingService settingService;

    @Autowired
    private EventOperContext context;

    /**
     * 注册
     * @param registerModel
     * @return
     */
    @Transactional
    public ResultModel register(RegisterModel registerModel, HttpServletRequest servletRequest){
        ResultModel checkRes = registCheck(registerModel);
        if(!checkRes.isSuccess()){
            return checkRes;
        }
        CCustomer customer = new CCustomer();
        customer.setCustNo(custNo());
        //customer.setUserName(registerModel.getUserName());
        customer.setMobile(registerModel.getUserName());
        customer.setPassword(DESCrypt.encrypt(registerModel.getPassword(), SysConstants.PASSWORD_ENCRYPT_KEY));
        customer.setFromend(HttpUtils.getDeviceType(servletRequest).getKey());
        customer.setCreateTime(new Date());
        customer.setStatus(EnumCommonStatus.Valid.getKey());
        customer.setRecommendCode(recNum());
        customer.setRecommender(registerModel.getRecommender());
        customer = logic.insertUserInfo(customer);
        if(customer.getId() != null && customer.getId()>0){
            createCustFundAccnt(customer);
            afterRegSuccess(customer);
        }else{
            LOG.info("用户信息:{}注册失败",registerModel);
            throw new RuntimeException("注册失败，请重试");
        }
        return ResultModel.success();
    }

    /**
     * 注册校验
     * @param registerModel
     * @return
     */
    private ResultModel registCheck(RegisterModel registerModel){
        if(StringUtils.isEmpty(registerModel.getUserName())){
            return ResultModel.failure(null,"请输入用户名");
        }
        if(!RegexUtils.isMobileSimple(registerModel.getUserName())){
            return ResultModel.failure(null,"请输入正确的手机号码");
        }
        if(StringUtils.isEmpty(registerModel.getPassword())){
            return ResultModel.failure(null,"请输入密码");
        }
        if(!RegexUtils.isMatch("[a-z0-9A-Z]{6,16}",registerModel.getPassword())){
            return ResultModel.failure(null,"请输入6-16位密码");
        }
        if(StringUtils.isEmpty(registerModel.getValidateNo())){
            return ResultModel.failure(null,"请输入验证码");
        }
        String cacheValidateNo = getStringFromQueue(EhCacheConstants.SmsPhoneNumCache,registerModel.getUserName());
        if(StringUtils.isEmpty(cacheValidateNo) || !cacheValidateNo.equals(registerModel.getValidateNo())){
            return ResultModel.failure(null,"请输入正确的验证码");
        }
        if(StringUtils.isNotEmpty(registerModel.getRecommendCode())){
            CCustomer tmp = logic.getByRecommendCode(registerModel.getRecommendCode());
            if(tmp == null){
                return ResultModel.failure(null,"不正确的推荐链接");
            }
            registerModel.setRecommender(tmp.getId());
        }
        //cahceEvict(EhCacheConstants.SmsPhoneNumCache, registerModel.getUserName());
        return ResultModel.success();
    }

    private void createCustFundAccnt(CCustomer customer){
        BigDecimal beanAmt = getSettingInfo(ConstantsSysSetting.T_REG,ConstantsSysSetting.C_REG001,BigDecimal.ZERO);
        BigDecimal iconAmt = getSettingInfo(ConstantsSysSetting.T_REG,ConstantsSysSetting.C_REG002,BigDecimal.ZERO);
        BigDecimal diamondAmt = getSettingInfo(ConstantsSysSetting.T_REG,ConstantsSysSetting.C_REG004,BigDecimal.ZERO);
        Date current = new Date();
        // 客户账户
        CCustomerfund tbFund = new CCustomerfund();
        tbFund.setBeanCnt(beanAmt);
        tbFund.setDiamondCnt(diamondAmt);
        tbFund.setIconCnt(iconAmt);
        tbFund.setUserId(customer.getId());
        tbFund.setCreateTime(current);
        tbFund = customerfundLogic.add(tbFund);
        if(tbFund.getId() == 0){
            throw new RuntimeException("注册失败，请重试");
        }

        // 客户账户流水
        // 注册金豆奖励
        CCustomerfundflow tbFundFlow = new CCustomerfundflow();
        tbFundFlow.setCustomerId(customer.getId());
        tbFundFlow.setAmount(beanAmt);
        tbFundFlow.setForm(EnumFundFlowForm.REWARD_REGISTER.getKey());
        tbFundFlow.setMetrialType(EnumMetrialType.Bean.getKey());
        tbFundFlow.setStartAmt(BigDecimal.ZERO);
        tbFundFlow.setEndAmt(BigDecimal.ZERO.add(beanAmt));
        tbFundFlow.setRemark("注册金豆奖励");
        tbFundFlow.setCreateTime(current);
        customerfundflowLogic.add(tbFundFlow);

        // 注册金币奖励
        CCustomerfundflow tbFundFlowIcon = new CCustomerfundflow();
        tbFundFlowIcon.setCustomerId(customer.getId());
        tbFundFlowIcon.setAmount(iconAmt);
        tbFundFlowIcon.setForm(EnumFundFlowForm.REWARD_REGISTER.getKey());
        tbFundFlowIcon.setMetrialType(EnumMetrialType.Icon.getKey());
        tbFundFlowIcon.setStartAmt(BigDecimal.ZERO);
        tbFundFlowIcon.setEndAmt(BigDecimal.ZERO.add(iconAmt));
        tbFundFlowIcon.setRemark("注册金币奖励");
        tbFundFlowIcon.setCreateTime(current);
        customerfundflowLogic.add(tbFundFlowIcon);

        // 注册彩钻奖励
        CCustomerfundflow tbFundFlowDiamond = new CCustomerfundflow();
        tbFundFlowDiamond.setCustomerId(customer.getId());
        tbFundFlowDiamond.setAmount(diamondAmt);
        tbFundFlowDiamond.setForm(EnumFundFlowForm.REWARD_REGISTER.getKey());
        tbFundFlowDiamond.setMetrialType(EnumMetrialType.Diamond.getKey());
        tbFundFlowDiamond.setStartAmt(BigDecimal.ZERO);
        tbFundFlowDiamond.setEndAmt(BigDecimal.ZERO.add(diamondAmt));
        tbFundFlowDiamond.setRemark("注册彩钻奖励");
        tbFundFlowDiamond.setCreateTime(current);
        customerfundflowLogic.add(tbFundFlowDiamond);

        //操作日志
        customerOperLogLogic.addOperInfo(EnumOperLogCategory.REGIST.getName(),"", customer.getId());
    }

    private BigDecimal getSettingInfo(String type,String code, BigDecimal curVal){
        List<SSetting> settings = settingService.getSettings(type);
        SSetting typeSetting = settings.stream().filter(x->{
           return x.getCode().equals(code);
        }).findFirst().orElse(null);
        if(typeSetting == null){
            return curVal;
        }else{
           return curVal.add(typeSetting.getAmtValue());
        }
    }

    /**
     * 注册成功后处理
     * @param customer
     */
    private void afterRegSuccess(CCustomer customer){
        QueueModel queueModel = new QueueModel();
        queueModel.setCustomerInfo(customer);
        queueModel.setEventType(EnumEventType.RegistEvent);
        context.putQueue(queueModel);
    }

    /**
     * 推荐码
     * @return
     */
    private String recNum(){
        String recommendNo = recommendNo();
        CCustomer custInfo = logic.getByRecommendCode(recommendNo);
        if(custInfo == null){
            return recommendNo;
        }else{
            return recNum();
        }
    }

    /**
     * 用户编号
     * @return
     */
    private String custNo(){
        return DateUtils.now("yyMMddHHmm") +  randomNumbers(3);
    }



}
